package com.dongbao.action;

import cn.hutool.core.util.ReferenceUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.system.SystemUtil;
import com.dongbao.common.AnalysisParam;
import com.dongbao.common.AuthorityEnum;
import com.dongbao.core.config.FlowChartState;
import com.dongbao.entity.CallMethod;
import com.dongbao.entity.TreeNode;
import com.dongbao.util.StorageConfig;
import com.dongbao.util.ToolUtil;
import com.dongbao.util.TreeNodeUtil;
import com.dongbao.util.XmindUtil;
import com.flow.annotations.FlowChart;
import com.flow.annotations.FlowChild;
import com.google.common.collect.Lists;
import com.intellij.codeInsight.externalAnnotation.location.AnnotationsLocationSearcher;
import com.intellij.lang.jvm.JvmMethod;
import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute;
import com.intellij.model.search.PsiSymbolReferenceSearcher;
import com.intellij.notification.*;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.search.MethodUsagesSearcher;
import com.intellij.psi.impl.search.PsiSearchHelperImpl;
import com.intellij.psi.impl.source.PsiJavaFileImpl;
import com.intellij.psi.impl.source.PsiMethodImpl;
import com.intellij.psi.impl.source.tree.PsiCommentImpl;
import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl;
import com.intellij.psi.impl.source.tree.java.*;
import com.intellij.psi.search.*;
import com.intellij.psi.search.searches.*;
import com.intellij.psi.util.PsiClassUtil;
import com.intellij.psi.util.PsiElementFilter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.refactoring.extractMethod.preview.ExtractMethodPreviewManager;
import com.intellij.ui.UIBundle;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Query;
import com.intellij.util.containers.MultiMap;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Element;
import org.xmind.core.*;
import org.xmind.core.internal.Boundary;
import org.xmind.core.internal.dom.NumberingImpl;
import org.xmind.core.internal.dom.TopicImpl;
import org.xmind.core.util.Point;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import static com.dongbao.common.AuthorityEnum.MAIN_ANNOTIONS_NAME;

@Slf4j
public class GenerateFlowAction extends AnAction {

  /** 文件分隔符 */
  public static final String FILE_SEPARATOR = SystemUtil.getOsInfo().getFileSeparator();

  private static final Logger LOG = Logger.getInstance(GenerateFlowAction.class);

  private Map<ITopic, TreeNode> relaseNode = new HashMap<ITopic, TreeNode>();

  @Override
  public void actionPerformed(@NotNull AnActionEvent e) {
    ProgressManager.getInstance()
        .run(
            new Task.Backgroundable(e.getProject(), e.getPresentation().getText(), false) {
              @Override
              public void run(@NotNull ProgressIndicator indicator) {
                ApplicationManager.getApplication()
                    .runReadAction(
                        () -> {
                          runGener(e, indicator);
                        });
              }
            });
  }

  @Nullable
  protected PsiClass getTargetClass(Editor editor, PsiFile file) {
    int offset = editor.getCaretModel().getOffset();
    PsiElement element = file.findElementAt(offset);
    if (element == null) {
      return null;
    } else {
      PsiClass target = PsiTreeUtil.getParentOfType(element, PsiClass.class);
      return target instanceof SyntheticElement ? null : target;
    }
  }
  /**
   * @description: 设置脑图项编号
   * @author: lirufei
   * @date: 2023/4/18 19:28
   * @param: iTopic
   * @return
   */
  @FlowChart("设置脑图项编号")
  private void setNumber(ITopic iTopic) {
    // flow:获取编号管理对象
    INumbering numbering = iTopic.getNumbering();
    // flow:设置显示编号
    numbering.setPrependsParentNumbers(true);
    numbering.setFormat("org.xmind.numbering.arabic");
    // flow:设置编号后缀为:
    numbering.setSuffix(":");
    if (iTopic.isRoot()) {
      ((NumberingImpl) numbering).getNumberingElement().setAttribute("number-depth", "10");
    }
    // number-depth="6"
    String title = iTopic.getTitleText();
    if (TreeNodeUtil.checkPatter(title, TreeNodeUtil.todoPatter)) {
      title = TreeNodeUtil.replaceString(title, TreeNodeUtil.todoPatter);
      iTopic.setTitleText(title);
      iTopic.addMarker("star-orange");
    }
    if (TreeNodeUtil.checkPatter(title, TreeNodeUtil.warnPatter)) {
      title = TreeNodeUtil.replaceString(title, TreeNodeUtil.warnPatter);
      iTopic.setTitleText(title);
      iTopic.addMarker("star-red");
    }
    if (TreeNodeUtil.checkPatter(title, TreeNodeUtil.corePatter)) {
      title = TreeNodeUtil.replaceString(title, TreeNodeUtil.corePatter);
      iTopic.setTitleText(title);
      iTopic.addMarker("flag-green");
    }
    // 标注  star-blue  star-red star-green
  }

  @FlowChart("生成脑图")
  private void runGener(AnActionEvent e, ProgressIndicator indicator) {
    // FLOW:数据检查：工程信息判断，如果为空生成失败，直接返回
    Project project = e.getData(LangDataKeys.PROJECT);
    if (project == null) {
      return;
    }
    //
    // PsiTreeUtil.getParentOfType()
    // FlOW:获取当前光标所在位置。
    Editor editor = e.getData(CommonDataKeys.EDITOR);
    // FlOW:获取当当前光标所对应的代码文件对象。
    PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
    // flow: 通过光标偏移量获取当前光标所在（psiElement）元素对象
    PsiElement currentElement = file.findElementAt(editor.getCaretModel().getOffset());
    // flow: 查找当前PsiElement元素所在方法（PsiMethodImpl）对象。
    PsiMethodImpl curMethod = PsiTreeUtil.getParentOfType(currentElement, PsiMethodImpl.class);
    // flow:获取当前文件的类（PsiClass）对象
    PsiClass target = PsiTreeUtil.getParentOfType(currentElement, PsiClass.class);
    // flow:获取当前文件的类（PsiClass）所包含的泛型对象（List<PsiClass>）
    List<PsiClass> genericClassList = getGenericClass(target);

    //  PsiMethodImpl curMethod = (PsiMethodImpl)e.getData(LangDataKeys.PASTE_TARGET_PSI_ELEMENT);
    // FlOW:判断当前光标所在方法是否有生成脑图注解
    if (curMethod != null
        && curMethod.hasAnnotation(MAIN_ANNOTIONS_NAME)
        && !isGroupMethod(curMethod)) {
      // flow:对当前方法生成脑图
      indicator.setText("处理单方法生成");
      // FlOW:获取方面注释名。
      String topic = methodAnnoValue(curMethod);
      // FlOW:生成脑图根对象。
      IWorkbook iWorkbook = generWorkbook(topic);
      ITopic rootTopic = iWorkbook.getPrimarySheet().getRootTopic();
      // flow：设置脑图项编号
      setNumber(rootTopic);

      StorageConfig config = FlowChartState.getInstance().getConfig();
      rootTopic.setStructureClass(config.getStructure());
      /* 调用方法的解析方法进行去解析方法内部的信息 */
      indicator.setText("处理思维导图节点");
      ToolUtil.createMethodInfo(rootTopic, curMethod, iWorkbook);
      List<PsiCommentImpl> allComments = new ArrayList<>();
      AnalysisParam analysisParam =
          new AnalysisParam(iWorkbook, target, genericClassList, allComments, 0);

      // FlOW:生成对应方法的脑图树
      ArrayList<ITopic> chapterTopics = analysisMethod(analysisParam, curMethod, rootTopic);

      String savePath = selectSavePath(project, iWorkbook, topic);
      //            // 保存
      //            try {
      //                iWorkbook.save(savePath + "\\" + FILE_SEPARATOR + topic + ".xmind");
      //                Runtime.getRuntime().exec("explorer /select, " +
      // savePath.replace("/",File.separator) + File.separator + topic + ".xmind");
      //            } catch (IOException ex) {
      //                ex.printStackTrace();
      //            } catch (CoreException ex) {
      //                ex.printStackTrace();
      //            }
    } else {
      // flow:对本类中全部满足条件的方法生成注解
      // 处理一组方法生成
      indicator.setText("对本类中全部满足条件的方法生成注解");
      // flow:获取当前类满足条件的方法集合
      PsiMethod[] methods = target.getAllMethods();
      if (methods.length > 0) {
        // FlOW:获取方面注释名。
        // String topic = methodAnnoValue(curMethod);
        // FlOW:生成脑图根对象。
        String title = String.format("类的全部脑图", target.getQualifiedName());
        IWorkbook iWorkbook = generWorkbook(title);
        ITopic rootTopic = iWorkbook.getPrimarySheet().getRootTopic();
        rootTopic.setTitleText(title);
        ToolUtil.createNotes(
            rootTopic, String.format("类:%s", target.getQualifiedName()), iWorkbook);
        // flow：设置脑图项编号
        // setNumber(rootTopic);

        StorageConfig config = FlowChartState.getInstance().getConfig();
        rootTopic.setStructureClass(config.getStructure());
        List<PsiCommentImpl> allComments = new ArrayList<>();
        AnalysisParam analysisParam =
            new AnalysisParam(iWorkbook, target, genericClassList, allComments, 0);

        for (int i = 0; i < methods.length; i++) {
          PsiMethod item = methods[i];
          if (item.hasAnnotation(MAIN_ANNOTIONS_NAME)) {
            String topic = methodAnnoValue(item);
            ITopic methodTopic = rootTopic.getOwnedWorkbook().createTopic();
            methodTopic.setTitleText(topic);
            ToolUtil.createMethodInfo(methodTopic, item, analysisParam.getWorkbook());
            rootTopic.add(methodTopic);
            setNumber(methodTopic);
            // FlOW:生成对应方法的脑图树
            analysisMethod(analysisParam, item, methodTopic);
          }
        }
        if (rootTopic.getAllChildren().size() > 0) {
          selectSavePath(
              project, iWorkbook, String.format("类(%s)全部方法对应的脑图", target.getQualifiedName()));
        } else {
          NotificationGroupManager.getInstance()
              .getNotificationGroup("FlowChart")
              .createNotification("提示", "没有找到满足条件的方法，生成失败！", NotificationType.INFORMATION)
              .notify(e.getProject());
          indicator.setText("没有找到满足条件的方法");
        }
      } else {
        indicator.setText("没有找到满足条件的方法");
      }
      //      PsiAnnotation annotations = curMethod.getAnnotation(MAIN_ANNOTIONS_NAME);
      //      JvmAnnotationAttribute curMethodGroup =
      //          annotations.getAttributes().stream()
      //              .filter(
      //                  item -> {
      //                    return item.getAttributeName().equals("group");
      //                  })
      //              .findAny()
      //              .orElse(null);
      //
      //      // 查找所有符合条件的方法
      //      //            AnnotationTargetsSearch.search();
      //      indicator.setText("筛选查找符合条件Method");
      //      GlobalSearchScope allScope = GlobalSearchScope.allScope(project);
      //      final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
      //      PsiClass presentation = psiFacade.findClass("com.flow.annotations.FlowChart",
      // allScope);
      //      //            final MultiMap<String, PsiAnnotation> annotations = new MultiMap<>();
      //      final List<PsiModifierListOwner> methods = new ArrayList<>();
      //
      //      indicator.setText("筛选符合当前组的Method");
      //      AnnotationTargetsSearch.search(presentation)
      //          .forEach(
      //              owner -> {
      //                PsiAnnotation annotation =
      //
      // owner.getModifierList().findAnnotation("com.flow.annotations.FlowChart");
      //                PsiAnnotationMemberValue group = annotation.findAttributeValue("group");
      //                if (group instanceof PsiLiteralExpression) {
      //                  Object value = ((PsiLiteralExpression) group).getValue();
      //                  if (value instanceof String
      //                      && ((PsiNameValuePairImpl)
      // curMethodGroup).getLiteralValue().equals(value)) {
      //                    //                        annotations.putValue((String)value,
      // annotation);
      //                    methods.add(owner);
      //                  }
      //                }
      //                return true;
      //              });
      //      indicator.setText("处理思维导图节点");
      //      // 调用处理集合中的方法 返回每个方法的节点渲染
      //      IWorkbook iWorkbook =
      //          generWorkbook(((PsiNameValuePairImpl) curMethodGroup).getLiteralValue());
      //      ITopic rootTopic = iWorkbook.getPrimarySheet().getRootTopic();
      //      for (PsiModifierListOwner psiModifierListOwner : methods) {
      //        PsiMethodImpl psiMethodImpl = (PsiMethodImpl) psiModifierListOwner;
      //        methodTopic(psiMethodImpl, rootTopic);
      //        System.out.println("处理完成！");
      //      }
      //      String fileName = rootTopic.getTitleText();
      //      String savePath = selectSavePath(project, iWorkbook, fileName);
    }
  }

  private ITopic methodTopic(PsiMethodImpl curMethod, ITopic rootTopic) {
    // 创建根节点下面的节点
    IWorkbook ownedWorkbook = rootTopic.getOwnedWorkbook();
    ITopic curMethodTopic = ownedWorkbook.createTopic();
    // 处理单方法生成
    String topic = methodAnnoValue(curMethod);
    curMethodTopic.setTitleText(topic);
    //        IWorkbook iWorkbook = generWorkbook(topic);
    //        StorageConfig config = FlowChartState.getInstance().getConfig();
    //        rootTopic.setStructureClass(config.getStructure());
    /* 调用方法的解析方法进行去解析方法内部的信息 */
    ArrayList<ITopic> chapterTopics = analysisMethod(null, curMethod, null);
    for (ITopic chindTopic : chapterTopics) {
      curMethodTopic.add(chindTopic);
    }
    rootTopic.add(curMethodTopic);
    return rootTopic;
  }

  public String selectSavePath(Project project, IWorkbook iWorkbook, String fileName) {
    AtomicReference<String> savePath = new AtomicReference<>();
    final FileChooserDescriptor dirChooser =
        FileChooserDescriptorFactory.createSingleFolderDescriptor();
    dirChooser.setShowFileSystemRoots(true);
    dirChooser.setHideIgnored(true);
    dirChooser.setTitle("选择思维导图保存路径");
    // alert 对话框
    //        EventQueue.invokeLater(() -> {
    //            FileChooser.chooseFiles(dirChooser, project, null, files -> {
    //                for (VirtualFile file : files) {
    //                    savePath.set(file.getPath());
    //                }
    //            });
    //        });
    ApplicationManager.getApplication()
        .invokeLater(
            () -> {
              FileChooser.chooseFiles(
                  dirChooser,
                  project,
                  null,
                  files -> {
                    for (VirtualFile file : files) {
                      //                    savePath.set(file.getPath());
                      // 保存
                      try {
                        iWorkbook.save(file.getPath() + "/" + fileName + ".xmind");
                        Runtime.getRuntime()
                            .exec(
                                "explorer /select, "
                                    + file.getPath().replace("/", File.separator)
                                    + File.separator
                                    + fileName
                                    + ".xmind");
                      } catch (IOException ex) {
                        ex.printStackTrace();
                      } catch (CoreException ex) {
                        ex.printStackTrace();
                      }
                    }
                  });
            });
    return savePath.get();
  }
  /**
   * @description: 获取注释的文本
   * @author: lirufei
   * @date: 2023/4/15 12:46
   * @param: element
   * @return
   */
  private String getCommentText(PsiElement element) {
    String rst = TreeNodeUtil.readerNodeContent(element);
    if (StringUtil.isNotEmpty(rst)) {
      rst = rst.replace("*/", "").trim();
    }
    return rst;
  }
  /**
   * @description: 获取下一个同级节点(跳过注释节点)
   * @author: lirufei
   * @date: 2023/4/15 12:49
   * @param: psiElement
   * @param: title
   * @return
   */
  private PsiElement getNextElement(PsiElement psiElement, StringBuilder title) {
    String tempText = getCommentText(psiElement);
    if (StringUtil.isNotEmpty(tempText)) {
      title.append(tempText);
    }
    PsiElement nextLeaf = psiElement.getNextSibling();
    if (nextLeaf != null && nextLeaf instanceof PsiCommentImpl) {
      tempText = getCommentText(nextLeaf);
      if (StringUtil.isNotEmpty(tempText)) {
        title.append(tempText);
      }
      return getNextElement(nextLeaf, title);
    } else if (nextLeaf instanceof PsiWhiteSpaceImpl) {
      return getNextElement(nextLeaf, title);
    } else {
      return nextLeaf;
    }
  }
  /**
   * @description: 根据语句类型，查找方法的调用体
   * @author: lirufei
   * @date: 2023/4/17 8:57
   * @param: psiElement
   * @return
   */
  private PsiElement[] findCallMethodExpression(PsiElement psiElement) {
    if (psiElement instanceof PsiIfStatementImpl) {
      return new PsiElement[] {((PsiIfStatementImpl) psiElement).getCondition()};
    } else if (psiElement instanceof PsiDeclarationStatementImpl) {
      return ((PsiDeclarationStatementImpl) psiElement).getDeclaredElements();
    } else if (psiElement instanceof PsiIfStatementImpl) {
      return new PsiElement[] {((PsiExpressionStatementImpl) psiElement).getExpression()};
    } else if (psiElement instanceof PsiWhileStatementImpl) {
      return new PsiElement[] {((PsiWhileStatementImpl) psiElement).getCondition()};
    } else if (psiElement instanceof PsiDoWhileStatementImpl) {
      return new PsiElement[] {((PsiDoWhileStatementImpl) psiElement).getCondition()};
    } else if (psiElement instanceof PsiForStatementImpl) {
      return new PsiElement[] {((PsiForStatementImpl) psiElement).getCondition()};
    } else if (psiElement instanceof PsiSwitchStatementImpl) {
      return new PsiElement[] {((PsiSwitchStatementImpl) psiElement).getExpression()};
    }
    return new PsiElement[] {psiElement};
  }
  /**
   * @description: 对方法生成脑图
   * @author: lirufei
   * @date: 2023/4/18 14:39
   * @param: analysisParam 公共请求参数
   * @param: method 要分析的方法对象
   * @param: parent 脑图节点
   * @return
   */
  @FlowChild("生成对应方法的脑图")
  private ArrayList<ITopic> analysisMethod(
      AnalysisParam analysisParam, PsiMethod method, ITopic parent) {
    ArrayList<ITopic> rst = Lists.newArrayList();
    // flow:备份老的注释防止在不同方法中调用同一个类导致注释被过滤
    List<Integer> oldComments = analysisParam.getComments();
    // flow:每个方法使用自己的注解
    List<Integer> curComments = new ArrayList<>();
    analysisParam.setComments(curComments);
    try {
      // FLOW:判断方法是否是引用
      if (method.getBody() == null) {
        // FLOW:如果是需要查找子类覆盖
        method = ovverMethod(method);
      }
      // FLOW:查找方法的代码块中的注解
      analysisMethod(analysisParam, method.getBody(), parent, 0);
      return rst;
    } finally {
      // flow:还原老的注释
      analysisParam.setComments(oldComments);
    }
  }
  /**
   * @description: 获取If语句的全部代码块
   * @author: lirufei
   * @date: 2023/4/18 13:17
   * @param: ifStatement
   * @return
   */
  @FlowChart("获取IF语句的全部代码块")
  private List<PsiBlockStatementImpl> getIfCodeBlock(PsiIfStatementImpl ifStatement) {
    List<PsiBlockStatementImpl> rst = new ArrayList<>();
    // FlOW:查询全部的代码块语句
    List<PsiBlockStatementImpl> codeBlocks =
        PsiTreeUtil.getChildrenOfTypeAsList(ifStatement, PsiBlockStatementImpl.class);
    if (!Objects.isNull(codeBlocks) && codeBlocks.size() > 0) {
      rst.addAll(codeBlocks);
    }
    // FlOW:查找同级的if语句
    List<PsiIfStatementImpl> ifStatements =
        PsiTreeUtil.getChildrenOfTypeAsList(ifStatement, PsiIfStatementImpl.class);
    if (!Objects.isNull(ifStatements) && ifStatements.size() > 0) {
      for (int i = 0; i < ifStatements.size(); i++) {
        PsiIfStatementImpl psiIfStatement = ifStatements.get(i);
        List<PsiBlockStatementImpl> tempRst = getIfCodeBlock(psiIfStatement);
        if (!Objects.isNull(tempRst) && tempRst.size() > 0) {
          rst.addAll(tempRst);
        }
      }
    }
    return rst;
  }

  @FlowChild("生成Switch语句的脑图")
  private List<ITopic> analysisSwitch(
      AnalysisParam analysisParam, PsiSwitchStatementImpl switchStatement, ITopic parent) {
    // FlOW:查询全部的 PsiBlockStatementImpl 代码块语句;
    PsiElement[] children = switchStatement.getBody().getChildren();
    if (!Objects.isNull(children) && children.length > 0) {
      boolean isBegin = true; // 重新开始分组
      for (int i = 0; i < children.length; i++) {
        PsiElement item = children[i];
        if (item instanceof PsiBlockStatementImpl) {
          // flow:以代码块为组生成脑图
          analysisMethod(analysisParam, item, parent, 1);
        } else {
          // 未处理，Label语句不是代码块未处理
        }
      }
    }
    return null;
  }

  @FlowChild("生成对应代码块的脑图")
  private ArrayList<ITopic> analysisMethod(
      AnalysisParam analysisParam, PsiElement codeBlock, ITopic parent, Integer type) {
    ArrayList<ITopic> chapterTopics = Lists.newArrayList();

    if (Objects.isNull(codeBlock)) {
      return chapterTopics;
    }
    analysisParam.setFirstTopic(null);
    // FLOW:1、查找方法体中间的注释对象。
    PsiTreeUtil.processElements(
        codeBlock,
        e -> {
          PsiCommentImpl t = ObjectUtils.tryCast(e, PsiCommentImpl.class);
          // FLOW:2、判断注释内容是否满足内置格式（FLOW:）。
          if (t != null && TreeNodeUtil.isFlowNode(t)) {
            if (type == 1 && analysisParam.getFirstTopic() == null || type != 1) {
              ITopic tempTopic = analyComment(analysisParam, t, parent, chapterTopics, type);
              if (tempTopic != null) {
                analysisParam.setFirstTopic(tempTopic);
              }
            } else {
              // 第二个注释，放在第一个注释下面
              analyComment(analysisParam, t, analysisParam.getFirstTopic(), chapterTopics, type);
            }
            return true;
          }
          return true;
        });
    return chapterTopics;
  }
  /**
   * @description:
   * @author: lirufei
   * @date: 2023/4/18 14:47
   * @param: analysisParam 公共请求参数
   * @param: comment 注释对象
   * @param: parent 脑图父节点
   * @param: chapterTopics
   * @param: type 父操作类型 1:If 2:for 3:while
   * @return
   */
  @FlowChild("生成注释的脑图")
  private ITopic analyComment(
      AnalysisParam analysisParam,
      PsiCommentImpl comment,
      ITopic parent,
      ArrayList<ITopic> chapterTopics,
      Integer type) {
    ITopic rst = null;
    if (comment != null && TreeNodeUtil.isFlowNode(comment)) {
      // FLOW:1、检查注释是否已经使用过
      if (analysisParam
          .getComments()
          .contains(Integer.valueOf(comment.hashCode() + comment.getParent().hashCode()))) {
        return null;
      }
      // FLOW:2、记录注释使用信息
      analysisParam
          .getComments()
          .add(Integer.valueOf(comment.hashCode() + comment.getParent().hashCode()));

      StringBuilder title = new StringBuilder();
      // FLOW:3、合并连续的注释内容和过滤空格，找到注释下面的最近元素（跳过空格）。
      PsiElement psiElement = getNextElement(comment, title);
      if (title.length() > 0) {
        // FLOW:4、根据注释内容生成节点。
        ITopic topic = parent.getOwnedWorkbook().createTopic();
        topic.setTitleText(title.toString());
        // flow：设置脑图项编号
        setNumber(topic);
        if (parent != null) {
          parent.add(topic);
        }
        rst = topic;
        // FLOW:5、判断当前处理对象是否是IF语句
        if (psiElement instanceof PsiIfStatementImpl) {
          // FLOW:6、判断IF语句是否启用了分级显示
          if (FlowChartState.getInstance().getConfig().getIfPartLevel()) {
            // 分级
            List<PsiBlockStatementImpl> ifCodes = getIfCodeBlock((PsiIfStatementImpl) psiElement);
            for (int i = 0; i < ifCodes.size(); i++) {
              PsiBlockStatementImpl psiBlockStatement = ifCodes.get(i);
              analysisMethod(analysisParam, psiBlockStatement, topic, 1);
            }
          }
        } else if (psiElement instanceof PsiSwitchStatementImpl) {
          if (FlowChartState.getInstance().getConfig().getIfPartLevel()) {
            // 分级
            analysisSwitch(analysisParam, (PsiSwitchStatementImpl) psiElement, topic);
          }
        } else if (psiElement instanceof PsiForStatementImpl
            || psiElement instanceof PsiDoWhileStatementImpl
            || psiElement instanceof PsiWhileStatementImpl
            || psiElement instanceof PsiForeachStatementImpl) {
          List<PsiBlockStatementImpl> codeBlocks =
              PsiTreeUtil.getChildrenOfTypeAsList(psiElement, PsiBlockStatementImpl.class);
          if (!Objects.isNull(codeBlocks)) {
            for (int i = 0; i < codeBlocks.size(); i++) {
              PsiBlockStatementImpl psiBlockStatement = codeBlocks.get(i);
              analysisMethod(analysisParam, psiBlockStatement, topic, 2);
            }
          }
        } else if (psiElement instanceof PsiBlockStatementImpl) {
          // flow:注释下是代码块时处理
          analysisMethod(analysisParam, psiElement, topic, 2);
        }
        // 检查是否需要循环调用方法
        // FLOW:7、检查是否调用了其它方法，如果调用了生成其它调用的脑图。
        PsiElement[] tempElements = findCallMethodExpression(psiElement);
        for (int m = 0; m < tempElements.length; m++) {
          final PsiElement tempElement = tempElements[m];
          // FLOW:8、儿子对象就是方法调用的情况。
          if (tempElement instanceof PsiMethodCallExpressionImpl) {
            analyMethodCallExpression(
                analysisParam, (PsiMethodCallExpressionImpl) tempElement, topic, chapterTopics);
          } else {
            // FLOW:8、儿子对象就是代码块，需要查找里面的方法调用对象。
            Collection<PsiMethodCallExpressionImpl> methodCalls =
                PsiTreeUtil.collectElementsOfType(
                    tempElements[m], PsiMethodCallExpressionImpl.class);
            methodCalls.forEach(
                methodCall -> {
                  if (methodCall != null) {
                    // 直接儿子才处理
                    analyMethodCallExpression(analysisParam, methodCall, topic, chapterTopics);
                  }
                });
          }
        }
      }
    }
    return rst;
  }
  /**
   * @description:调用代码块生成脑图
   * @author: lirufei
   * @date: 2023/4/18 14:53
   * @param: analysisParam 公共请求参数
   * @param: methodCall 方法调用对象
   * @param: parent 脑图父节点
   * @param: chapterTopics
   * @return
   */
  @FlowChild("生成方法调用对象脑图")
  private void analyMethodCallExpression(
      AnalysisParam analysisParam,
      PsiMethodCallExpressionImpl methodCall,
      ITopic parent,
      ArrayList<ITopic> chapterTopics) {
    PsiClass target = analysisParam.getTarget();
    List<PsiClass> genericClassList = analysisParam.getGenericClassList();
    if (methodCall != null) {
      PsiMethod nextMethod = methodCall.resolveMethod();
      PsiReferenceExpression methodExpression = methodCall.getMethodExpression();
      PsiExpression psiExpression = methodExpression.getQualifierExpression();
      // FLOW:1、判断调用表达式对象是否是引用对象
      if (psiExpression instanceof PsiReferenceExpression) {
        // FLOW:2、查找调用方法对象是否是类里面的属性

        String fieldClassName =
            ((PsiReferenceExpressionImpl) psiExpression).getReference().getCanonicalText();
        // flow:如果不是类名，检查是否是字段属性
        if (!fieldClassName.contains(".")) {
          String fieldName = ((PsiReferenceExpression) psiExpression).getReferenceName();
          if (fieldName != null) {
            // FLOW:3、通过字段类型获取调用者的类
            PsiField field = target.findFieldByName(fieldName, true);
            if (field != null) {
              fieldClassName = field.getType().getInternalCanonicalText();
            }
          }
        }
        // 东宝内部类或者泛型
        if ((StringUtil.isNotEmpty(fieldClassName) && fieldClassName.startsWith("com.dongbao"))
            || (fieldClassName.length() == 1 && StringUtil.isUpperCase(fieldClassName))) {
          // FLOW:3、通过字段类型获取调用者的类
          PsiClass psiClass =
              JavaPsiFacade.getInstance(psiExpression.getProject())
                  .findClass(
                      fieldClassName, GlobalSearchScope.projectScope(psiExpression.getProject()));
          // FLOW:4、如果获取不到类信息，判断是否是泛型引入类。
          if (genericClassList.size() > 0 && psiClass == null) {
            // 是否考虑循环
            psiClass = genericClassList.get(0);
          }
          if (psiClass != null) {
            // FLOW:5、查询全部实现类。
            Query<PsiClass> search = ClassInheritorsSearch.search(psiClass);
            Collection<PsiClass> tempClass = search.findAll();
            PsiMethod tempM = nextMethod;
            if (tempClass.size() > 0) {
              tempClass.forEach(
                  item -> {
                    String className = null;
                    String titel = parent.getTitleText();
                    if (TreeNodeUtil.checkPatter(titel, TreeNodeUtil.classPatter)) {
                      className = TreeNodeUtil.getClassName(titel);
                      parent.setTitleText(
                          TreeNodeUtil.replaceClassName(titel, TreeNodeUtil.classPatter));
                    }
                    if (className != null && !item.getName().equalsIgnoreCase(className)) {
                      return;
                    }
                    // FLOW:6、查询全部实现类中的方法。
                    PsiMethod tempMethod = item.findMethodBySignature(tempM, true);
                    String topic = getAnnotionTitle(tempMethod);
                    if (StringUtil.isNotEmpty(topic)) {
                      ITopic subtopic = null;
                      // FLOW:7、如果父亲的注释和方法的注释一样不重新创建节点
                      if (parent.getTitleText().equals(topic)) {
                        subtopic = parent;
                      } else {
                        subtopic = parent.getOwnedWorkbook().createTopic();
                        subtopic.setTitleText(topic);
                        // flow：设置脑图项编号
                        setNumber(subtopic);
                        parent.add(subtopic);
                        // subtopic.getNumbering().setPrependsParentNumbers(false);
                      }
                      // flow:方法调用后重新设置序号级别
                      NumberingImpl numbering = (NumberingImpl) subtopic.getNumbering();
                      if (numbering != null && numbering.getNumberingElement() != null) {
                        numbering.getNumberingElement().setAttribute("number-depth", "10");
                      }
                      // Element tempTopic = ((TopicImpl) topic).getImplementation();
                      ToolUtil.createMethodInfo(subtopic, tempMethod, analysisParam.getWorkbook());
                      // FLOW:8、生成方法的脑图
                      analysisMethod(analysisParam, tempMethod, subtopic);
                    }
                  });
              return;
            }
          }
        }
      } else if (psiExpression instanceof PsiMethodCallExpressionImpl) {
        // flow:方法前面是方法调用对象。
        PsiClass methodClass =
            JavaPsiFacade.getInstance(psiExpression.getProject())
                .findClass(
                    ((PsiMethodCallExpressionImpl) psiExpression)
                        .resolveMethod()
                        .getReturnType()
                        .getInternalCanonicalText(),
                    GlobalSearchScope.projectScope(psiExpression.getProject()));
        if (methodClass != null) {
          PsiMethod tempMethod = methodClass.findMethodBySignature(nextMethod, true);
          if (tempMethod != null) {
            if (tempMethod.hasAnnotation(MAIN_ANNOTIONS_NAME)) {
              nextMethod = tempMethod;
            } else {
              String className = null;
              String titel = parent.getTitleText();
              if (TreeNodeUtil.checkPatter(titel, TreeNodeUtil.classPatter)) {
                className = TreeNodeUtil.getClassName(titel);
                parent.setTitleText(TreeNodeUtil.replaceClassName(titel, TreeNodeUtil.classPatter));
              }
              nextMethod = ovverMethod(tempMethod, className);
            }
          }
        }
      }
      // FLOW:2、本类中的方法或者可以直接找到调用类的方法
      if (nextMethod != null
          && nextMethod.getContainingClass().getQualifiedName().startsWith("com.dongbao")) {
        // FlOW:获取方法注释名。
        String topic = getAnnotionTitle(nextMethod);
        if (StringUtil.isNotEmpty(topic)) {
          ITopic subtopic = parent.getOwnedWorkbook().createTopic();
          subtopic.setTitleText(topic);
          // Element tempTopic = ((TopicImpl) topic).getImplementation();
          ToolUtil.createMethodInfo(subtopic, nextMethod, analysisParam.getWorkbook());
          setNumber(subtopic);
          parent.add(subtopic);
          // subtopic.getNumbering().setPrependsParentNumbers(false);
          // flow:方法调用后重新设置序号级别
          NumberingImpl numbering = (NumberingImpl) subtopic.getNumbering();
          if (numbering != null && numbering.getNumberingElement() != null) {
            numbering.getNumberingElement().setAttribute("number-depth", "10");
          }
          List<ITopic> nextTopics = analysisMethod(analysisParam, nextMethod, subtopic);
          if (nextTopics != null && nextTopics.size() > 0) {
            chapterTopics.addAll(nextTopics);
          }
        }
      }
    }
  }

  /** 判断是否是组合生成 */
  private Boolean isGroupMethod(PsiMethod method) {
    PsiAnnotation annotations = method.getAnnotation(MAIN_ANNOTIONS_NAME);
    if (annotations == null) {
      return false;
    }
    List<JvmAnnotationAttribute> attributes = annotations.getAttributes();
    for (JvmAnnotationAttribute attribute : attributes) {
      if (attribute.getAttributeName().equals("group")
          && attribute.getAttributeValue() != null
          && StringUtil.isNotEmpty(attribute.getAttributeValue().toString())) {
        return true;
      }
    }
    return false;
  }

  /** 从方法的顶部注解获取注解中的Value值 */
  @FlowChild("获取方面注释名")
  private String methodAnnoValue(PsiMethod method) {
    if (method.getBody() == null) {
      // 如果方法体为null 则 去查找当前方法是否有实现方法。
      method = ovverMethod(method);
    }
    return getAnnotionTitle(method);
  }
  /**
   * @description: 获取注解说明内容
   * @author: lirufei
   * @date: 2023/4/17 17:12
   * @param: method
   * @return
   */
  private String getAnnotionTitle(PsiMethod method) {
    StringBuilder topic = new StringBuilder();
    if (method == null) {
      return topic.toString();
    }
    PsiAnnotationImpl mainAnnotion = (PsiAnnotationImpl) method.getAnnotation(MAIN_ANNOTIONS_NAME);
    PsiAnnotationImpl childAnnotion =
        (PsiAnnotationImpl) method.getAnnotation(AuthorityEnum.CHILD_ANNOTIONS_NAME);
    try {
      if (mainAnnotion != null) {
        topic.append(mainAnnotion.findAttributeValue("value").getText().replace("\"", ""));
      }
      if (childAnnotion != null) {
        topic.append(
            String.format(
                "(%s)", childAnnotion.findAttributeValue("value").getText().replace("\"", "")));
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return topic.toString();
  }
  /** 创建一个生成 思维导图的对象 */
  @FlowChild("生成脑图根对象")
  private IWorkbook generWorkbook(String topic) {
    /* 定义一个流程图的对象 */
    // 创建思维导图的工作空间
    IWorkbookBuilder workbookBuilder = Core.getWorkbookBuilder();
    IWorkbook workbook = workbookBuilder.createWorkbook();

    // 获得默认sheet
    ISheet primarySheet = workbook.getPrimarySheet();
    // 获得根主题
    ITopic rootTopic = primarySheet.getRootTopic();
    // 设置根主题的标题
    rootTopic.setTitleText(topic);
    // 章节 topic 的列表
    // ArrayList<ITopic> chapterTopics = Lists.newArrayList();
    // 把章节节点添加到要节点上
    // chapterTopics.forEach(it -> rootTopic.add(it, ITopic.ATTACHED));
    return workbook;
  }

  @Override
  public void update(@NotNull final AnActionEvent e) {
    try {
      PsiElement data2 = e.getData(LangDataKeys.PASTE_TARGET_PSI_ELEMENT);
      if (data2 instanceof PsiMethodImpl) {
        PsiMethodImpl curMethod = (PsiMethodImpl) data2;
        PsiAnnotation[] annotations = curMethod.getAnnotations();
        /* 判断是否有生成流程图的注解 */
        Boolean enable = false;
        for (PsiAnnotation annotation : annotations) {
          PsiAnnotationImpl annotationImpl = (PsiAnnotationImpl) annotation;
          if (MAIN_ANNOTIONS_NAME.equals(annotationImpl.getQualifiedName())
              || AuthorityEnum.CHILD_ANNOTIONS_NAME.equals(annotationImpl.getQualifiedName())) {
            /* 是声明的流程图注解 */
            enable = true;
            break;
          }
        }
        e.getPresentation().setVisible(enable);
      }
    } catch (Exception exce) {
      e.getPresentation().setEnabled(false);
    }
  }
  /**
   * @description: 查找全部继承方法
   * @author: lirufei
   * @date: 2023/4/21 20:41
   * @param: method
   * @param: className
   * @return
   */
  private PsiMethod ovverMethod(PsiMethod method, String className) {
    // method.getContainingFile().
    Collection<PsiMethod> allMethod =
        OverridingMethodsSearch.search(method, method.getContainingClass().getUseScope(), true)
            .findAll();
    Iterator<PsiMethod> iterator = allMethod.iterator();
    // hasNext():判断是否还下一个元素
    while (iterator.hasNext()) {
      // next():①指针下移 ②将下移以后集合位置上的元素返回
      method = iterator.next();
      if (method.hasAnnotation(MAIN_ANNOTIONS_NAME)
          && (className == null
              || method.getContainingClass().getName().equalsIgnoreCase(className))) {
        break;
      }
    }
    return method;
  }
  /**
   * @description:查找全部继承方法
   * @author: lirufei
   * @date: 2023/4/21 20:42
   * @param: method
   * @return
   */
  private PsiMethod ovverMethod(PsiMethod method) {
    return ovverMethod(method, null);
  }
  /**
   * @description: 查找类的泛型注入类
   * @author: lirufei
   * @date: 2023/4/18 9:58
   * @param: srcClass 需要分析的类对象
   * @return 返回类使用的泛型类，如没有返回list长度为0
   */
  private List<PsiClass> getGenericClass(PsiClass srcClass) {
    // srcClass.getExtendsList().getReferenceElements()[0].getParameterList().getTypeParameterElements()[0].getType().getInternalCanonicalText()
    ArrayList classs = new ArrayList();
    // 判断类是否有继承类
    if (Objects.isNull(srcClass.getExtendsList())) {
      return null;
    }
    // 获取继承类的引用元素
    PsiJavaCodeReferenceElement[] typeElements = srcClass.getExtendsList().getReferenceElements();
    if (Objects.isNull(typeElements)) {
      return null;
    }
    for (int i = 0; i < typeElements.length; i++) {
      // 如果引用元素没有参数，说明没有泛型注入类跳出
      if (Objects.isNull(typeElements[i].getParameterList())) {
        continue;
      }
      // 获取泛型类的类型
      PsiTypeElement[] parameterElementTypes =
          typeElements[i].getParameterList().getTypeParameterElements();
      for (int j = 0; j < parameterElementTypes.length; j++) {
        // 根据泛型类型的类名称获取类对象。
        PsiClass psiClass =
            JavaPsiFacade.getInstance(srcClass.getProject())
                .findClass(
                    parameterElementTypes[j].getType().getInternalCanonicalText(),
                    GlobalSearchScope.projectScope(srcClass.getProject()));
        // 如果类不空添加到返回列表里面
        if (psiClass != null) {
          classs.add(psiClass);
        }
      }
    }
    return classs;
  }
}
